removido
(usa Nenhuma)
Enviado em 17/08/2012 - 23:51h
Vamos lá:
paulo1205 escreveu:
Listeiro 037 escreveu:
"7" não é um dígito e nem um caracter. É uma string também. Em notação de vetor seria:
argv[4]={'7','{TEXTO}'}
Entendo que você quis dizer argv[4]={'7', 0};, e que foi o programa do fórum que trocou o sinal de contrabarra seguido de "0" por essa string "{TEXTO}".
Isso seria da construção do fórum. A tal ' \ 0 ' se for escrita sem os espaços como deve-se escrever em C apareceria como '{TEXTO}'.
paulo1205 escreveu:
Listeiro 037 escreveu:
"char argv[]" é um array de caracteres. "char *argv[]" é um array de ponteiros de caracteres. Se ao invés de argv fosse
char *string0="prog1"
char *string1="abc"
char *string2="de2"
char *string3="345"
char *string4="7"
que também pode ser escrito como:
char string0[]="prog1"
char string1[]="abc"
char string2[]="de2"
char string3[]="345"
char string4[]="7"
onde os colchetes estão vazios porque não se indica ou sabe-se o tamanho da string. Então ficaria
argv = { *string0, *string1, *string2, *string3, *string4 }
ou
argv = { string0[], string1[], string2[], string3[], string4[] }
No caso ele indica em que parte da memória estão os parãmetros. Então argv é um ponteiro. As sequências string0[], string1[]... também são ponteiros para caracteres.
Seria bom destacar que nada do que vai acima é C (i.e. não compilaria), mas uma construção parecida com fins meramente didáticos. Mas, nesse caso, acho que seria mais apropriado dizer que "os colchetes estão vazios para que o compilador calcule o tamanho da string e crie arrays com os tamanhos mínimos necessários para armazenar os dados indicados" (admitindo-se, por exemplo, uma declaração como
char string2[]="de2";, é óbvio que o tamanho do array é 4, e não desconhecido).
[/quote]
Escrevi o texto de uma vez só e evitei de ficar reformatando por muito tempo. Estava esperando a pessoa que criou o tópico dizer que não entendeu prá tentar remendar. :\
Nem pensei se compilaria ou não, mas agora fiquei interessado em testar algumas sintaxes. Exceto por esse número à frente da variável, que não é um índice. Realmente quem desconhece pode pensar isto. Não sei se isso seria pior do que criar um nome aleatório para representar cada elemento no vetor de parâmetros. Lembrarei-me disto algum dia no futuro.
Não ousaria dizer exatamente a notação que 'tentei' fazer, mas posso dizer que prefiro isso do que portugol. Não me preocupei com o rigor do formalismo, mas com uma outra abordagem.
Quando você escreve
char a[] = "abcd" é óbvio que você vê quatro caracteres após o sinal de igual. Mas e o tal barra-zero? É quatro ou é cinco? E se a string tivesse 1337 caracteres? E se fossem 1338? Nesse sentido desconhece-se quantos caracteres há na string. Não precisa contar, saber, pensar em quantos há exatamente. Inclusive
char a[] = "abcd" é
char *a = "abcd"
No vetor de parâmetros a situação é semelhante. Quem "sabe" quantos parâmetros há é o outro parâmetro.
Eu nem quis dizer que main() possui três parâmetros prá não complicar mais a coisa. ¬¬
paulo1205 escreveu:
O fato é que é uma coisa muito infeliz para iniciantes a forma como C trabalha com strings. E mesmo outros tipos de arrays estão longe de ser intuitivos para quem não tem ainda alguma familiaridade com programação.
Mesmo assim alguns compreenderam e não tenho a menor ideia de como o fizeram.
paulo1205 escreveu:
Listeiro 037 escreveu:
Se houvesse apenas uma string no parâmetro, no caso *string0 ou string[] porque não é dito o tamanho, argv apontaria apenas para ela.
*argv -> *string0
É um ponteiro para um ponteiro, que pode ser escrito como **argv, notação antiga usada dentro de main().
Mas como arg é um vetor, então
*argv -> { *string0, *string1, *string2, *string3, *string4 }
E por não se expressar também o tamanho desse vetor, escreve-se
*argv[]
ou
**argv por ser um ponteiro que aponta para ponteiros.
Não consegui ver a lógica desse salto lógico, mas tudo bem.
Garanto que não foi o único. ¬¬
paulo1205 escreveu:
Além do mais, eu penso que "notação antiga", se há, é a que usa colchetes, pois ela era a notação original para designar ponteiros em B, a linguagem que antecedeu o C. O asterisco veio anos depois, já com o C.
Escrevi essa referência pela memória. Eu li uma recomendação de que há uma notação a ser evitada pelo desuso, mas se eu encontrar onde eu li, creio que não será importante. Quanto ao B, vou pensar no caso.
paulo1205 escreveu:
Sobre essa notação, é interessante notar o seguinte: quando os colchetes vazios são usados numa declaração de argumento de função, eles são um sinônimo perfeito da declaração feita apenas com asterisco (i.e. int main(int argc, char **argv) é exatamente a mesma coisa que int main(int argc, char *argv[]), em que argv é literalmente uma "variável do tipo ponteiro para dados do tipo ponteiro para dados do tipo char", deixando bem clara a herança da notação de B). Há quem argumente que se deva preferir "[]" quando se for usar o endereço associado ao ponteiro para acesso a vários elementos em adjacentes na memória, e asteriscos quando o uso principal for a referência a um único elemento, residente apenas no endereço indicado pelo ponteiro. Entendo os motivos, mas discordo da abordagem.
Tudo bem. Eu discordo de comparar uma linguagem de 40 anos atrás com uma de 50 anos atrás, um ano a mais ou a menos, não importa. A coisa já está muito complicada em facilitar alguma explicação com este nó que eu fiz. Eu me preocupava mais em tentar diagramar numa linguagem acessível. Mas se quer saber, conseguiu me fazer dar a mínima.
Caracteres de texto são muito menos flexíveis para diagramar que papel. Eu escrevi como me veio à mente no momento e em poucos minutos e pareceu-me claro. Não é unanimidade. Agora nunca será mesmo.
paulo1205 escreveu:
No entanto, quando não se tratar da declaração de um argumento de função, o que se terá é um array, não uma variável do tipo ponteiro (faço essa distinção porque o nome de um array, ainda que, quando usado, tenha o valor de um endereço de memória, não é uma variável porque não é um lvalue). E o cálculo do tamanho mímino necessário sempre ocorre: por exemplo, se se delcarar um array de caracteres sem se especificar seu tamanho nem se lhe definir um valor inicial (como em char vc[];), o compilador gerará um array de tamanho 1, suficiente apenas para armazenar o byte nulo.
A situação de 'saber' o valor implica em contar o número de caracteres. O compilador sabe porque ele contou. Eu posso não ter contado. Esse caso é o 'não se sabe'. "O compilador que se vire".
Entendi o caso do lvalue, mas o exemplo não teve tempo de ser tão aprofundado. Não houve o rigor do formalismo. Fora isso peço mais nada.
Se houvesse erro em tempo de compilação, ficaria mais fácil explicar o que houve.
Listeiro 037 escreveu:
Perceba que o único modo de conseguir usar os ponteiros ou parâmetros do vetor argv[] é com o auxílio de argc, informado justamente para isto.
paulo1205 escreveu:
Talvez isso seja verdade em geral, mas acho interessante observar que não é verdade nos UNIXes em geral, e particularmente no Linux.
Um novo programa é sempre chamado pela system call
execve(), que recebe, entre seus argumentos, um
argv, do tipo
char **, mas nada parecido com um inteiro
argc. Essa função conta os argumentos de modo parecido com a forma como strings identificam o final da cadeia de caracteres: usando um marcador com valor nulo como último elemento do array. Esse marcador nulo, que deve estar presente quando
execve() é invoca é passado por ela ao novo programa qur ela abre. Desse modo, é seguro fazer no Linux algo como vai abaixo.
int main(int argc, char **argv){
assert(argv[argc]==NULL);
/* ... */
}
Se o assunto é Unix-Like, melhor, Linux, não é uma verdade geral.
Só há um problema: estamos falando da função main() que usa uma variável que recebe um valor inteiro. Se vocẽ quiser usar essa execve que conta os parâmetros ao invés, aí é outra história ... :-P A exemplo do último parâmetro de main() pode ser acessada com uma função sem usar o parâmetro. Falei sobre isso lá atrás.
OBS: Faltou explicar a função assert() :-P
*** EDIT ***
etc.